package monitor

import (
	"fmt"
	"sync"
	"time"

	"gitee.com/rw555/fdsmastergo/pkg/config"
	"gitee.com/rw555/fdsmastergo/pkg/device"
	"gitee.com/rw555/fdsmastergo/pkg/keypad"
	"gitee.com/rw555/fdsmastergo/pkg/logger"
	"gitee.com/rw555/fdsmastergo/pkg/state"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

type Monitor struct {
	configClient *config.Client
	currentTemp  int
	power        int
	ticker       *time.Ticker
	quit         chan struct{}
	cmdChan      chan Command
	mode         state.Mode
	device       device.Device
	keyScanner   keypad.Scanner
	systemConfig map[string]interface{}
	configMutex  sync.RWMutex

	// 自动模式相关时间记录
	currentWorkingMinutes int
	autoModeStartTime     time.Time // 自动模式开始时间
	autoModeStopTime      time.Time // 自动模式结束时间
	lastDbUpdateTime      time.Time // 上次更新数据库的时间
}

func NewMonitor(dev device.Device, keyScanner keypad.Scanner) (*Monitor, error) {
	// 加载配置
	configClient := config.NewClient("http://localhost:8082")
	systemConfig, err := configClient.LoadConfigs()
	if err != nil {
		return nil, fmt.Errorf("加载配置失败: %w", err)
	}
	configClient.PrintConfigs(systemConfig)
	m := &Monitor{
		ticker:       nil,
		quit:         make(chan struct{}),
		cmdChan:      make(chan Command),
		mode:         state.ModeNone,
		device:       dev,
		keyScanner:   keyScanner,
		systemConfig: systemConfig,
		configClient: configClient,
	}

	// 使用互斥锁保护配置访问
	m.configMutex.RLock()
	timerInterval := time.Duration(int(m.systemConfig["monitor.timer_interval"].(float64))) * time.Millisecond
	m.configMutex.RUnlock()

	m.ticker = time.NewTicker(timerInterval)

	return m, nil
}

func (m *Monitor) Start() {
	m.keyScanner.SetCallback(m)
	m.keyScanner.Start()

	go func() {
		for {
			select {
			case cmd := <-m.cmdChan:
				m.handleCommand(cmd)
			case <-m.ticker.C:
				m.TimerProc()
			case <-m.quit:
				m.ticker.Stop()
				return
			}
		}
	}()
}

func (m *Monitor) Stop() {
	m.keyScanner.Stop()
	close(m.quit)
}

func (m *Monitor) RefreshConfig(c *gin.Context) error {
	// 从配置服务获取最新配置
	newConfig, err := m.configClient.LoadConfigs()
	if err != nil {
		logger.SystemError("获取最新配置失败", zap.Error(err))
		return err
	}

	// 使用互斥锁保护配置更新
	m.configMutex.Lock()
	defer m.configMutex.Unlock()

	// 更新本地配置
	m.systemConfig = newConfig
	logger.SystemInfo("配置已刷新")
	return nil
}

func (m *Monitor) handleCommand(cmd Command) {
	switch cmd.Type {
	case CommandTypeKey:
		m.HandleKeyCommand(cmd.Data.(KeyCommandData))
	case CommandTypeEvent:
		m.HandleEventCommand(cmd.Data.(EventCommandData))
	}
}

func (m *Monitor) GetStatus() (int, int, []string, bool, bool, int) {
	heater1Status, _ := m.device.IsHeater1Open()
	heater2Status, _ := m.device.IsHeater2Open()
	pumpStatus, _ := m.device.PumpIsRunning()

	// 如果任一加热器开启，则认为加热状态为开启
	heatingStatus := heater1Status || heater2Status

	return m.currentTemp, m.power, []string{m.mode.String()}, heatingStatus, pumpStatus, m.currentWorkingMinutes
}

func (m *Monitor) SetMode(mode string, option string) error {
	err := fmt.Errorf("设置模式失败")
	if mode == state.ModeAuto.String() {
		if option == "stop" {
			err = m.StopAutoMode()
		} else if option == "start" {
			err = m.StartAutoMode()
		}
	} else if mode == state.ModeForceHeat.String() {
		if option == "stop" {
			err = m.StopForceHeat()
		} else if option == "start" {
			err = m.StartForceHeat()
		}
	} else if mode == state.ModeForcePump.String() {
		if option == "stop" {
			err = m.StopForcePump()
		} else if option == "start" {
			err = m.StartForcePump()
		}
	}
	return err
}

// UpdateAutoModeInfo 定期更新自动模式状态，每 minDuration（默认5分钟） 分钟记录一次
func (m *Monitor) UpdateAutoModeInfo() {
	now := time.Now()
	m.currentWorkingMinutes = int(now.Sub(m.autoModeStartTime).Minutes())

	minDuration := int(m.systemConfig["monitor.automode_min_duration"].(float64))
	if now.Sub(m.lastDbUpdateTime).Minutes() >= float64(minDuration) {
		m.lastDbUpdateTime = now
		err := m.saveAutoModeSession(m.autoModeStartTime, now)
		if err != nil {
			logger.SystemError("保存自动模式记录失败", zap.Error(err))
		}
	}
}

// saveAutoModeSession 保存自动模式会话记录到数据库
func (m *Monitor) saveAutoModeSession(startTime, endTime time.Time) error {
	// 直接调用configClient的SaveAutoModeSession方法
	return m.configClient.SaveAutoModeSession(startTime, endTime)
}
